/**
 * 
 */
package jmine.tec.report;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import jmine.tec.report.metadata.ColumnMetaData;
import jmine.tec.report.metadata.ParameterDefinition;
import jmine.tec.report.metadata.ParameterType;

/**
 * Describes a DataTable
 * 
 * @author takeshi
 * @version 29/08/2007
 */
public interface TableDescriptor extends Serializable {

    /**
     * Gets the columns defined is this column descriptor
     * 
     * @return {@link List} of {@link ColumnMetaData}
     */
    List<DataColumn> getColumns();

    /**
     * @param column {@link ColumnMetaData} to add
     * @return {@link TableDescriptor} itself
     */
    DataColumn addColumn(ColumnMetaData column);

    /**
     * Adiciona uma column factory, usando a {@link ColumnMetaData} dada como descritor
     * 
     * @param factory a {@link ColumnFactory}
     * @param meta a {@link ColumnMetaData}
     */
    void addColumnFactory(ColumnFactory factory, ColumnMetaData meta);

    /**
     * Adiciona uma column factory fazendo o curry
     * 
     * @param factory a column factory
     * @param meta o metadata
     * @param paramsToCurry os parametros
     */
    void addColumnFactoryCurry(ColumnFactory factory, ColumnMetaData meta, Map<String, Object> paramsToCurry);

    /**
     * Gets a column by its index
     * 
     * @param index the index
     * @return {@link DataColumn}
     */
    DataColumn getColumn(int index);

    /**
     * Gets the number of columns available in this {@link TableDescriptor}
     * 
     * @return int
     */
    int getNumberOfColumn();

    /**
     * @param key the Key
     * @param name the name
     * @param params the params
     * @return {@link DataColumn} the column just added
     */
    DataColumn addColumn(final String key, final String name, ParameterDefinition... params);

    /**
     * @param key the Key
     * @param name the name
     * @param paramsToCurry the map of parameters to curry on this column
     * @param params the params
     * @return {@link DataColumn} the column just added
     * @deprecated prefira {@link #addColumnCurry(ColumnMetaData, Map)}
     */
    @Deprecated
    DataColumn addColumnCurry(final String key, final String name, Map<String, Object> paramsToCurry,
            ParameterDefinition... params);

    /**
     * Adiciona uma coluna
     * 
     * @param meta o {@link ColumnMetaData} da coluna a ser adicionada
     * @param paramsToCurry os parametros a serem fixos
     * @return {@link DataColumn} a coluna adicionada
     */
    DataColumn addColumnCurry(final ColumnMetaData meta, Map<String, Object> paramsToCurry);

    /**
     * @param param a string
     * @return o object
     */
    Object getParam(final String param);

    /**
     * Sets a parameter value, if the parameter type is compatible with the given value.
     * 
     * @param param o param�metro
     * @param obj o objeto
     */
    void setParameterValue(final String param, final Object obj);

    /**
     * Returns the parameter values.
     * 
     * @return {@link Map}
     */
    Map<String, Object> getParameterValues();

    /**
     * Gets the parameter type
     * 
     * @param paramName String
     * @return {@link ParameterType}
     */
    ParameterType getParameterType(final String paramName);

    /**
     * Subclasses must override default hashCode
     * 
     * @return int
     */
    int hashCode();

    /**
     * Subclasses must override default {@link Object#equals(Object)}
     * 
     * @param obj the object to compare to
     * @return boolean
     */
    boolean equals(Object obj);

    /**
     * Gets a {@link Map} that contains all parameter definitions from all the columns. Modifications on the returned {@link Map} should not
     * reflect on this {@link TableDescriptor}.
     * 
     * @return {@link Map}
     */
    Map<String, ParameterDefinition> getMergedParameterDefinition();

    /**
     * Creates an {@link ExecutableDataTable} with the columns from this {@link ExecutableDataTable}.
     * 
     * @param container {@link ExecutableDataColumnContainer} the container from witch to purge columns
     * @return {@link ExecutableDataTable}
     */
    ExecutableDataTable buildExecutableDataTable(ExecutableDataColumnContainer container);

    /**
     * Removes the column with the given index
     * 
     * @param index the index
     */
    void removeColumnWithIndex(int index);

    /**
     * Revalidates the parameters. Should be called if the list of columns is changed.
     */
    void revalidateParameters();
}
